import path from 'path';
import fsPromise from 'fs-promise';
// @ts-ignore
import colors from 'colors-console';

const si = require('../../ext/systeminformation');
import sleep from '../lib/sleep';
import RSATool from '../lib/RSATool';
import getServerInfo from '../lib/System/getServerInfo';

let configInit = false;

const defaultBaseConfig = {
        'name': '地理数据汇聚管理平台',
        'version': 'v3.5',
        'version_time': '2025-08-22',
        'clientCORS': true,
        'clientCORS_desc': '是否允许跨域请求主服务的API接口',
        'protocol': 'http',
        'protocol_desc': '启动本程序 HTTP 服务器的协议，http 或 https',
        'httpServerPort': 3000,
        'httpServerPort_desc': '启动本程序 HTTP 服务器，发布服务的端口号',
        'proxyProtocol': 'https',
        'proxyProtocol_desc': '经过网关、交换机、防火墙等一系列代理后，外部网络访问本程序 Web 服务的协议号',
        'proxyAfterProxy_Port': 3000,
        'proxyAfterProxy_Port_desc': '经过网关、交换机、防火墙等一系列代理后，外部网络访问本程序 HTTP 服务的端口号',
        'localIPAddress': '127.0.0.1',
        'localIPAddress_desc': '在局域网内网中，部署本程序宿主机的 IP 地址',
        'proxyAfterProxy_IPAddress': '127.0.0.1',
        'proxyAfterProxy_IPAddress_desc': '经过网关、交换机、防火墙等一系列代理后，外部网络访问本程序 HTTP 服务的 IP 地址',
        'normalDBExt': '.sqlite3',
        'normalDBExt_desc': '普通地理资源数据库文件扩展名，如：.sqlite3',
        'encryptDBExt': '.enDB',
        'encryptDBExt_desc': '加密地理资源库数据库文件扩展名，如：.enDB',
        'encryptDBCache': false,
        'encryptDBCache_desc': '是开启地理资源请求时，将结果数据保存并写入资源库的插件',
        'blackList': [],
        'blackList_desc': '黑名单列表，禁止访问本程序 HTTP 服务的客户端 IP 地址',
        'wwwPath': 'www',
        'MapBox': {
            'access_token': 'pk.eyJ1Ijoic3ZjLW9rdGEtbWFwYm94LXN0YWZmLWFjY2VzcyIsImEiOiJjbG5sMnExa3kxNTJtMmtsODJld24yNGJlIn0.RQ4CHchAYPJQZSiUJ0O3VQ',
            'header': {
                'Referer': 'https://geojson.io/'
            }
        },
        'TianDiTu': {
            'tk': ''
        },
        'CacheSave': {
            'CacheSaveFile': true,
            'CacheSaveDB': false
        },
        'userList': [
            {
                'userName': 'user_1',
                'nickname': '访客',
                'password': '123456',
                'role': 'client'
            },
            {
                'userName': 'admin',
                'nickname': '指挥员',
                'password': '123456',
                'role': 'manage'
            }
        ],
        'publicDer': '',
        'privateDer': '',
        'desc': '服务器端配置文件，具体字段的说明和填写规范，可查阅源码工程目录下的 ./src/com/configTool.ts 文件'
    }
;
const defaultServiceConfig: any = {};
const configTool = {
    appBasePath: '',
    wwwPath: '',
    serverInfo: {
        'arch': null,
        'PCName': null,
        'memorySize': null,
        'operatingSystem': null,
        'CPU': null,
        'machineId': ''
    },
    baseConfig: defaultBaseConfig,
    serviceConfig: defaultServiceConfig,
    async editConfig(key: string, value: any) {
        await this.init();
        let result = false;
        if (typeof this.baseConfig[key] === typeof value) {
            this.baseConfig[key] = value;
            await fsPromise.writeJSON(path.join(this.appBasePath, '/conf/baseConfig.json'), this.baseConfig);
            result = true;
        }
        return result;
    },
    async saveServerConfig(json: any) {
        await fsPromise.writeJSON(path.join(this.appBasePath, '/conf/serviceConfig.json'), json);
        this.serviceConfig = json;
    },
    async init() {
        return new Promise(async (resolve, reject) => {
            if (!configInit) {
                configInit = true;

                // 是否处于开发环境
                let isDev = !__dirname.includes('snapshot');

                if (isDev) {
                    this.appBasePath = path.join(__dirname, '../../');
                } else {
                    this.appBasePath = path.dirname(process.execPath);
                }

                this.serverInfo = await getServerInfo();

                await fsPromise.ensureDir(path.join(this.appBasePath, '/conf'));
                await fsPromise.ensureDir(path.join(this.appBasePath, '/temp/fileOut'));
                await fsPromise.ensureDir(path.join(this.appBasePath, '/temp/fileDB'));
                await fsPromise.ensureDir(path.join(this.appBasePath, '/temp/fileDB/upload'));
                await fsPromise.ensureDir(path.join(this.appBasePath, '/temp/logs/httpServer'));
                await fsPromise.ensureDir(path.join(this.appBasePath, '/www'));
                await fsPromise.ensureDir(path.join(this.appBasePath, '/www/MapResources'));

                let configFile = path.join(this.appBasePath, '/conf/baseConfig.json');
                let serviceFile = path.join(this.appBasePath, '/conf/serviceConfig.json');


                // 判断是否读取本地已有的配置文件
                await fsPromise.readJson(configFile).then((d: any) => {
                    if (d.version === defaultBaseConfig.version) {
                        this.baseConfig = d;
                    } else {
                        console.log(colors('red', '----|||配置文件版本过低，未生效！！请重置配置文件|||----'));
                        resolve(false);
                    }
                }).catch(() => {
                    // 新生成一份配置文件
                    this.baseConfig = defaultBaseConfig;
                    const {privateDer, publicDer} = RSATool.createKey(2048);
                    this.baseConfig.privateDer = privateDer;
                    this.baseConfig.publicDer = publicDer;

                    fsPromise.writeJSON(configFile, this.baseConfig);
                });

                await fsPromise.readJson(serviceFile).then((d: any) => {
                    this.serviceConfig = d;
                }).catch(() => {
                    fsPromise.writeJSON(serviceFile, this.serviceConfig);
                });


                if (this.baseConfig.localIPAddress === 'localhost') {
                    let networks = await si.networkInterfaces();
                    networks = networks.filter((item: any) => item.ip6subnet);

                    // 查找 默认网卡，如果找不到则采用 第一个网卡
                    let defaultNet = networks.find((item: any) => item.default);
                    if (!defaultNet) {
                        defaultNet = networks[0];
                    }

                    this.baseConfig.localIPAddress = defaultNet?.ip4 || '127.0.0.1';
                }

                // 判断wwwPath是否是绝对路径
                if (path.isAbsolute(this.baseConfig.wwwPath)) {
                    this.wwwPath = path.join(this.baseConfig.wwwPath);
                } else {
                    this.wwwPath = path.join(this.appBasePath, this.baseConfig.wwwPath);
                }
            }

            while (!configInit) {
                await sleep(50);
            }
            resolve(true);
        });

    },
    preservableONDB() {
        return this.baseConfig.CacheSave.CacheSaveDB;
    },
    preservableONFile() {
        return this.baseConfig.CacheSave.CacheSaveFile;
    }
};


export default configTool;
